#include <iostream>

#include "SFSClient.h"

using std::cout;
using std::endl;

#define THREAD_NUM 1

string g_log_conf_file;

int parse_args(int argc, char * argv[]) {
        char c;
        while(-1 != (c = getopt(argc, argv, "l:"))) {
                switch(c) {
                        case 'l':
                                g_log_conf_file = optarg;
                                break;

                        default:
                                break;
                }
        }
}

string gen_rand_dir_name(const char * parent_dir) {
	string ret = parent_dir;
	for (int i = 0; i < 10; i++) {
		char c = rand() % 26 + 'a';
		ret += c;
	}
	return ret;
}

string gen_rand_file_path(const char * parent_dir) {
	string ret = parent_dir;
	for (int i = 0; i < 10; i++) {
		char c = rand() % 26 + 'a';
		ret += c;
	}
	return ret;
}

void * test_create_and_delete_dir_routine(void * arg) {
	SFSClient sfs;
	int ret = sfs.init(g_log_conf_file.c_str(), "127.0.0.1", 3501,  30, 10, 10, 10, -1);
	if (ret < 0) { cout << "init fail" << endl; return NULL; }
	while (true) {
		string dir_name = gen_rand_dir_name("/");
		ret = sfs.create_dir(dir_name.c_str());
		if (ret < 0) { cout << "create dir fail" << endl; return NULL; }
		ret = sfs.delete_dir(dir_name.c_str());
		if (ret < 0) { cout << "delete dir fail:" << endl; return NULL; }
	}
	return NULL;
}

void * test_truncate_routine(void * arg) {
	SFSClient sfs;
	int ret = sfs.init(g_log_conf_file.c_str(), "127.0.0.1", 3501,  30, 10, 10, 10, -1);
	if (ret < 0) { cout << "init fail" << endl; return NULL; }
	while (true) {
		string file_path = gen_rand_file_path("/");
		ret = sfs.create_file(file_path.c_str());
		if (ret < 0) { cout << "create file fail" << endl; return NULL; }
		int buf_len = 100;
		char * buf = new char[buf_len];
		for (int i = 0; i < buf_len; i++) buf[i] = 'a';
		ret = sfs.write_file(file_path.c_str(), buf, buf_len, 0, DS_WRITE_MODE_APPEND);
		delete[] buf;
		if (ret < 0) { cout << "write file error, ret:" << ret << endl; return NULL; }
		ret = sfs.truncate(file_path.c_str(), 0);
		if (ret < 0) { cout << "truncate file error, ret:" << ret << endl; return NULL; }
		cout << "truncate file ok" << endl;
		return NULL;
	}
	return NULL;
}

int test_create_and_delete_dir() {
	pthread_t t[THREAD_NUM];
	for (int i = 0; i < THREAD_NUM; i++) {
		pthread_create(&t[i], NULL, test_create_and_delete_dir_routine, NULL);
	}
	for (int i = 0; i < THREAD_NUM; i++) {
		pthread_join(t[i], NULL);
	}
	return 1;
}

int test_truncate() {
	pthread_t t[THREAD_NUM];
	for (int i = 0; i < THREAD_NUM; i++) {
		pthread_create(&t[i], NULL, test_truncate_routine, NULL);
	}
	for (int i = 0; i < THREAD_NUM; i++) {
		pthread_join(t[i], NULL);
	}
	return 1;
}

void * test_create_and_delete_file_routine(void * arg) {
	SFSClient sfs;
	int ret = sfs.init(g_log_conf_file.c_str(), "127.0.0.1", 3501,  30, 10, 10, 10, -1);
	if (ret < 0) { cout << "init fail" << endl; return NULL; }
	while (true) {
		string file_path = gen_rand_file_path("/");
		ret = sfs.create_file(file_path.c_str());
		if (ret < 0) { cout << "create file fail" << endl; return NULL; }
		cout << "file:" << file_path << ", size:" << sfs.get_file_size(file_path.c_str());
		ret = sfs.delete_file(file_path.c_str());
		if (ret < 0) { cout << "delete file fail:" << endl; return NULL; }
		return NULL;
	}
	return NULL;
}

void * test_read_and_write_file_routine(void * arg) {
	SFSClient sfs;
	int ret = sfs.init(g_log_conf_file.c_str(), "127.0.0.1", 3501,  30, 10, 10, 10, -1);
	if (ret < 0) { cout << "init fail" << endl; return NULL; }
	while (true) {
		string file_path = gen_rand_file_path("/");
		ret = sfs.create_file(file_path.c_str());
		if (ret < 0) { cout << "create file fail" << endl; return NULL; }
		int len1 = 8 * 1024 * 1024 - 100;
		char * buf = new char[len1];
		for (int i = 0; i < len1; i++) buf[i] = 'a';
		ret = sfs.write_file(file_path.c_str(), buf, len1, 0, DS_WRITE_MODE_APPEND);
		if (ret < 0) { cout << "write file 1 error, ret:" << ret << endl; return NULL; }
		for (int i = 0; i < len1; i++) buf[i] = 'b';
		ret = sfs.write_file(file_path.c_str(), buf, len1, 0, DS_WRITE_MODE_APPEND);
		if (ret < 0) { cout << "write file 2 error, ret:" << ret << endl; return NULL; }
		int len2 = 4 * 1024 * 1024 - 100;
		int begin_pos = 2 * 1024 * 1024 + 10;
		char * buf2 = new char[len2];
		for (int i = 0; i < len2; i++) buf2[i] = 'c';
		ret = sfs.write_file(file_path.c_str(), buf2, len2, begin_pos, DS_WRITE_MODE_NORMAL);
		if (ret < 0) { cout << "write file 1 error, ret:" << ret << endl; return NULL; }
		int len3 = 100;
		char * buf3 = new char[len3];
		bzero(buf3, len3);
		ret = sfs.read_file(file_path.c_str(), buf3, 9 * 1024 * 1024 - 100, len3 - 1);
		if (ret < 0) { cout << "read file error, ret:" << ret << endl; return NULL; } 
		cout << buf3 << endl;
		return NULL;
	}
	return NULL;


}

int test_create_and_delete_file() {
	pthread_t t[THREAD_NUM];
	for (int i = 0; i < THREAD_NUM; i++) {
		pthread_create(&t[i], NULL, test_create_and_delete_file_routine, NULL);
	}
	for (int i = 0; i < THREAD_NUM; i++) {
		pthread_join(t[i], NULL);
	}
	return 1;
}

int test_read_and_write_file() {
	pthread_t t[THREAD_NUM];
	for (int i = 0; i < THREAD_NUM; i++) {
		pthread_create(&t[i], NULL, test_read_and_write_file_routine, NULL);
	}
	for (int i = 0; i < THREAD_NUM; i++) {
		pthread_join(t[i], NULL);
	}
	return 1;
}

int init() {
	srand(time(NULL));
}

int main(int argc, char * argv[]) {
	parse_args(argc, argv);
	init();
	return test_truncate();
	//return test_read_and_write_file();
	//return test_create_and_delete_file();
	//return test_create_and_delete_dir();
}
